package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import com.tanhua.autoconfig.templates.OssTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.CommentApi;
import com.tanhua.dubbo.api.MovementApi;
import com.tanhua.dubbo.api.UserInfoApi;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.Comment;
import com.tanhua.model.mongo.Movement;
import com.tanhua.model.vo.MovementsVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class MovementsService {

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private MovementApi movementApi;

    @DubboReference
    private UserInfoApi userInfoApi;

    @DubboReference
    private CommentApi commentApi;

    @Autowired
    private StringRedisTemplate redisTemplate; //处理字符串类型的数据

    @Autowired
    private MqMessageService mqMessageService;

    //发布动态
    public void movements(MultipartFile[] imageContent, String textContent, String location, String longitude, String latitude) throws IOException {
        //1、构建动态对象
        Movement movement = new Movement();
        movement.setUserId(UserHolder.getUserId());
        movement.setTextContent(textContent);
        movement.setLocationName(location);
        movement.setLatitude(latitude);
        movement.setLongitude(longitude);
        movement.setCreated(System.currentTimeMillis());
        //2、将图片上传到阿里云oss上
        List<String> medias = new ArrayList<>();
        for (MultipartFile image : imageContent) {
            String imageUrl = ossTemplate.upload(image.getInputStream(), image.getOriginalFilename());
            medias.add(imageUrl);
        }
        //3、设置到Movement对象中
        movement.setMedias(medias);
        //4、调用API保存
        String id = movementApi.save(movement);
        //发送MQ消息，用于动态审核
        mqMessageService.sendAudiMessage(id);
    }

    //查询个人发布的动态
    public PageResult all(Integer page, Integer pagesize, Long userId) {
        //1、调用API根据用户id，查询此用户发布的动态列表  List<Movement>
        List<Movement> list = movementApi.findByUserId(userId,page,pagesize);
        //2、判断动态列表是否为空
        if(CollUtil.isEmpty(list)) {
            return new PageResult();
        }
        //3、循环List<Movement>，一个Movement构建一个MovementVo对象
        //3.1、根据用户id，查询用户信息
        UserInfo info = userInfoApi.findById(userId);
        List<MovementsVo> vos = new ArrayList<>();
        //3.2一个Movement构建一个MovementVo对象
        for (Movement movement : list) {  //
            //需要动态发布人的用户信息
            MovementsVo vo = MovementsVo.init(info, movement);
            //从redis中查询点赞状态,如果有点赞状态，设置为1
            String redisKey = Constants.MOVEMENTS_INTERACT_KEY+vo.getId();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            Boolean hasKey = redisTemplate.opsForHash().hasKey(redisKey, hashKey);
            if(hasKey) {
                vo.setHasLiked(1);
            }
            //从redis中查询喜欢状态,如果有喜欢状态，设置为1
            String loveKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
            Boolean hasLoveKey = redisTemplate.opsForHash().hasKey(redisKey, loveKey);
            if(hasLoveKey) {
                vo.setHasLoved(1);
            }
            vos.add(vo);
        }
        //4、返回
        return new PageResult(page,pagesize,0l,vos);
    }

    //查询好友动态
    public PageResult findByFriendsId(Integer page, Integer pagesize) {
        //1、获取当前用户id，查询的friendId条件
        Long friendId = UserHolder.getUserId();
        //2、调用API根据friendId查询动态列表  List<Movement>
        List<Movement> list = movementApi.findByFriendId(friendId,page,pagesize);
        //3、调用公共方法，构造返回
        return initPage(list,page,pagesize);
    }

    //公共的方法
    private PageResult initPage (List<Movement> list,Integer page, Integer pagesize) {
        //3、判断动态列表是否为空
        if(CollUtil.isEmpty(list)) {
            return new PageResult();
        }
        //一次性，将list中所有的动态发布人查询出来
        //a：提取list中的所有动态发布人id
        List<Long> userIds = CollUtil.getFieldValues(list, "userId", Long.class);//list，属性名，类型
        //b：调用UserInfoApi，查询多个用户的用户信息
        Map<Long,UserInfo> map = userInfoApi.findByIds(userIds);
        //4、循环List<Movement>，一个Movement构建一个MovementVo对象
        List<MovementsVo> vos = new ArrayList<>();
        for (Movement movement : list) {
            Long userId = movement.getUserId();//获取动态发布人
            UserInfo info = map.get(userId); //直接从map获取
            //UserInfo info = userInfoApi.findById(userId);//查询动态发布人的信息
            //调用MovementsVo工具方法init构建
            MovementsVo vo = MovementsVo.init(info, movement);//用户信息，动态详情
            String redisKey = Constants.MOVEMENTS_INTERACT_KEY+vo.getId();
            String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
            Boolean hasKey = redisTemplate.opsForHash().hasKey(redisKey, hashKey);
            if(hasKey) {
                vo.setHasLiked(1);
            }
            String loveKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
            Boolean hasLoveKey = redisTemplate.opsForHash().hasKey(redisKey, loveKey);
            if(hasLoveKey) {
                vo.setHasLoved(1);
            }
            vos.add(vo);
        }
        //5、返回
        return new PageResult(page,pagesize,0l,vos);
    }

    /**
     * 查询推荐动态
     *  1、查询redis中的数据。
     *  2、如果reids中数据不存在，随机从MongoDB中提取动态数据展示
     */
    public PageResult findByRecommend(Integer page, Integer pagesize) {
        //1、获取用户id
        Long userId = UserHolder.getUserId();
        //2、从redis中查询，推荐的动态数据
        String key = "MOVEMENTS_RECOMMEND_"+userId;
        String value = redisTemplate.opsForValue().get(key);
        //3、判断动态数据是否存在
        List<Movement> list = new ArrayList<>();
        if(!StringUtils.isEmpty(value)) {
            //3.1 如果存在，获取数据中的所有id，调用API根据动态的id列表，查询动态详情   List<Movement>
            String[] movementIds = value.split(",");
            list = movementApi.findByIds(movementIds,page,pagesize);
        }else{
            //3.2 数据不存在，调用API随机查询动态列表  List<Movement>
            list = movementApi.randomMovement(pagesize);
        }
        //4、调用公共方法，构造返回
        return initPage(list,page,pagesize);
    }

    //根据id查询动态
    public MovementsVo findById(String id) {
        //调用API查询  Movement
        Movement movement = movementApi.findById(id);
        //获取动态发布人
        Long userId = movement.getUserId();
        UserInfo userInfo = userInfoApi.findById(userId);
        //Movement转化MovementsVo
        return MovementsVo.init(userInfo,movement);
    }

    //点赞
    public Integer like(String id) {
        Integer commentType = 1;
        //1、调用API保存互动数据，更新动态表
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(id));
        comment.setCommentType(commentType);
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());
        Integer count = commentApi.save(comment);//此方法需要修改（保存评论）
        //2、将点赞状态，存入redis（为了方便查询点赞状态）
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + id;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(redisKey,hashKey,"1"); //rediskey，hashkey，数据
        //3、发送日志消息
        mqMessageService.sendLogMessage(UserHolder.getUserId(),"0203","log.movement",
                id); //用户id，日志类型，路由键，业务id（动态，视频id）
        return count;
    }

    //取消点赞
    public Integer dislike(String movementId) {
        Integer commentType = 1;
        Long userId = UserHolder.getUserId();
        //1、调用API删除互动数据，更新动态表(用户id，动态id，操作类型)
        Integer count = commentApi.delete(userId,commentType,movementId);
        //2、删除Redis中的点赞状态
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LIKE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(redisKey,hashKey);//rediskey , hashKey
        return count;
    }

    //喜欢
    public Integer love(String movementId) {
        Integer commentType = 3; //喜欢
        //1、调用API保存
        Comment comment = new Comment();
        comment.setPublishId(new ObjectId(movementId));
        comment.setCommentType(commentType);
        comment.setUserId(UserHolder.getUserId());
        comment.setCreated(System.currentTimeMillis());
        Integer count = commentApi.save(comment);
        //2、记录喜欢状态到redis中
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().put(redisKey,hashKey,"1");
        return count;
    }

    //取消喜欢
    public Integer unlove(String movementId) {
        Integer commentType = 3; //喜欢
        Long userId = UserHolder.getUserId();
        //1、调用API删除互动数据，更新动态表(用户id，动态id，操作类型)
        Integer count = commentApi.delete(userId,commentType,movementId);
        //2、删除redis中的，喜欢状态
        String redisKey = Constants.MOVEMENTS_INTERACT_KEY + movementId;
        String hashKey = Constants.MOVEMENT_LOVE_HASHKEY + UserHolder.getUserId();
        redisTemplate.opsForHash().delete(redisKey,hashKey);
        return count;
    }
}
